package org.bjf.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.bjf.modules.core.web.interceptor.LoginInterceptor;
import org.bjf.modules.core.web.interceptor.UrlInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * Created by binjinfeng on 2017/3/16.
 */
@Configuration
@ConditionalOnClass(WebMvcConfigurerAdapter.class)
public class WebConfig extends WebMvcConfigurerAdapter {

  @Resource
  private UrlInterceptor urlInterceptor;
  @Resource
  private LoginInterceptor loginInterceptor;

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    //调用父类的配置
    super.configureMessageConverters(converters);
    //创建fastJson消息转换器
    FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
    //创建配置类
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    //修改配置返回内容的过滤
    fastJsonConfig.setSerializerFeatures(
        // 格式化
        SerializerFeature.PrettyFormat,
        // 可解决long精度丢失 但会有带来相应的中文问题
        //SerializerFeature.BrowserCompatible,
        // 消除对同一对象循环引用的问题，默认为false（如果不配置有可能会进入死循环）
        SerializerFeature.DisableCircularReferenceDetect,
        // 是否输出值为null的字段,默认为false
        SerializerFeature.WriteMapNullValue,
        // 字符类型字段如果为null,输出为"",而非null
        SerializerFeature.WriteNullStringAsEmpty,
        // List字段如果为null,输出为[],而非null
        SerializerFeature.WriteNullListAsEmpty
    );
    // 日期格式
    fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
    //处理中文乱码问题
    List<MediaType> fastMediaTypes = new ArrayList<>();
    fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
    fastJsonConverter.setSupportedMediaTypes(fastMediaTypes);
    fastJsonConverter.setFastJsonConfig(fastJsonConfig);
    //将fastjson添加到视图消息转换器列表内
    converters.add(fastJsonConverter);
  }


  /*
  jackson 写法
  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    //不包含为空的字段
    builder.serializationInclusion(JsonInclude.Include.NON_NULL);
    //不包含空字符串字段
//    builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
    builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    //自定义Long类型转换 超过12个数字用String格式返回，由于js的number只能表示15个数字
    builder.serializerByType(Long.class,new CustomLongConverter());
    builder.serializerByType(Long.TYPE,new CustomLongConverter());
    converters.add(0,new MappingJackson2HttpMessageConverter(builder.build()));
  }*/

  /**
   * 拦截器
   */
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(urlInterceptor).addPathPatterns("/**");
    registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
  }

  /**
   * cors 跨域支持 可以用@CrossOrigin在controller上单独设置
   */
  @Bean
  public CorsFilter corsFilter() {

    //1.添加CORS配置信息
    CorsConfiguration config = new CorsConfiguration();
    //放行哪些原始域
    config.addAllowedOrigin("*");
    //是否发送Cookie信息
    config.setAllowCredentials(Boolean.TRUE);
    //放行哪些原始域(请求方式)
    config.addAllowedMethod("*");
    //放行哪些原始域(头部信息)
    config.addAllowedHeader("*");

    //2.添加映射路径
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);

    //3.返回新的CorsFilter
    return new CorsFilter(source);

  }

  /**
   * 404 处理
   */
  @Bean
  public EmbeddedServletContainerCustomizer containerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
      @Override
      public void customize(ConfigurableEmbeddedServletContainer container) {
        container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
      }
    };
  }
}
